package evaluator

import (
	"monkey/object"
)

var builtins = map[string]*object.Builtin{
	"len":&object.Builtin{Fn:lenFunc,},
	"first":&object.Builtin{Fn:firstFunc},
	"last":&object.Builtin{Fn:lastFunc},
	"rest":&object.Builtin{Fn:restFunc},
	"push":&object.Builtin{Fn:pushFunc},
	"puts":&object.Builtin{Fn:putsFunc},
	//"iter":&object.Builtin{Fn:iterFunc},
}
var lenFunc = func(args ...object.Object) object.Object{
	if len(args) != 1{
		return newError("wrong number of arguments. got=%d, want=1",len(args))
	}
	switch arg := args[0].(type){
	case *object.String:
		return &object.Integer{Value:int64(len(arg.Value))}
	case *object.Array:
		return &object.Integer{Value:int64(len(arg.Elements))}
	default:
		return newError("argument to `len` not supported, got %s",args[0].Type())
	}
}

var firstFunc = func(args ...object.Object) object.Object{
	if len(args) != 1{
		return newError("wrong number of arguments. got=%d, want=1",len(args))
	}
	if args[0].Type() != object.ARRAY_OBJ{
		return newError("argument to `first` must be Array, got %s",args[0].Type())
	}
	arr := args[0].(*object.Array)
	if len(arr.Elements) > 0{
		return arr.Elements[0]
	}
	return NULL
}

var lastFunc = func(args ...object.Object) object.Object{
	if len(args) != 1{
		return newError("wrong number of arguments. got=%d, want=1",len(args))
	}
	if args[0].Type() != object.ARRAY_OBJ{
		return newError("argument to `last` must be Array, got %s",args[0].Type())
	}
	arr := args[0].(*object.Array)
	if len(arr.Elements) > 0{
		return arr.Elements[len(arr.Elements) - 1]
	}
	return NULL
}

var restFunc = func(args ...object.Object) object.Object{
	if len(args) != 1{
		return newError("wrong number of arguments. got=%d, want=1",len(args))
	}
	if args[0].Type() != object.ARRAY_OBJ{
		return newError("argument to `last` must be Array, got %s",args[0].Type())
	}
	arr := args[0].(*object.Array)
	length := len(arr.Elements)
	if length > 0{
		newElements := make([]object.Object,length-1,length-1)
		copy(newElements,arr.Elements[1:length])
		return &object.Array{Elements: newElements}
	}
	return NULL
}

var pushFunc = func(args ...object.Object) object.Object{
	if len(args) != 2{
		return newError("wrong number of arguments. got=%d. want=2",len(args))
	}
	if args[0].Type() != object.ARRAY_OBJ{
		return newError("argument to `push` must be Array, got %s",args[0].Type())
	}
	arr := args[0].(*object.Array)
	length := len(arr.Elements)
	newElements := make([]object.Object,length+1,length+1)
	copy(newElements,arr.Elements)
	newElements[length] = args[1]
	return &object.Array{Elements: newElements}
}

//TODO:实现iter,reduce，map，sum等内置函数
// var iterFunc  func(...object.Object) object.Object

// iterFunc = func(args ...object.Object) object.Object{
	
// }

var putsFunc = func(args ...object.Object) object.Object{
	var stringPut string 
	for _,arg := range args{
		stringPut=stringPut+arg.Inspect()
	}
	return &object.String{Value:stringPut}
}